package com.aliware.tianchi.test.random;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author lorne
 * @date 2019/6/30
 * @description
 */
class UniformDistributionTool {

    private int maxSize;

    private Map<Double,PointVal> points;

    private AtomicInteger total ;

    UniformDistributionTool(int maxSize, double[] chances) {
        this.maxSize =maxSize;
        this.points = new ConcurrentHashMap<>();
        this.total = new AtomicInteger();
        double chance = 0.0;
        for(double v:chances){
            chance =chance+v;
            double value = chance*maxSize;
            PointVal pointVal = new PointVal(v,chance,maxSize);
            points.put(value,pointVal);
        }

        if(chance!=1.0){
            throw new RuntimeException(chance+"  don't satisfy 1.0 .");
        }
    }

    double next(){
        double val =  (Math.random()*this.maxSize);
        PointVal count = getCount(val);
        count.getCount().incrementAndGet();
        if(count.canGet()){
            count.getCount().decrementAndGet();
            return next();
        }
        total.incrementAndGet();
        return val;
    }


    boolean finish(){
        return total.get()>=maxSize;
    }


    int nextInt(){
        int val =  (int)(Math.random()*this.maxSize+1);
        PointVal count = getCount(val);
        count.getCount().incrementAndGet();
        if (count.canGet()) {
            count.getCount().decrementAndGet();
            return nextInt();
        }
        total.incrementAndGet();
        return val;
    }

    private PointVal getCount(double val) {
        for (double v:points.keySet()){
            PointVal pointVal = points.get(v);
            if(val>pointVal.getMinVal()&&val<=pointVal.getMaxVal()){
                return pointVal;
            }
        }
        return null;
    }

}
